package com.tedu.object.day01;



import org.junit.Test;
import org.omg.CORBA.LongHolder;

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
import java.math.BigDecimal;
import java.math.BigInteger;

/** 答题系统---
 *
 *  API---会使用类、抽象类、接口类、异常---分包，解决类重名：知道类在那个包下
 *  会查： 怎么查：通过包找对应类：抽象类、接口类、异常  （开发手册：70%基本现成类）
 *
 *  Java是面向对象，基本类型不具备面向对象的特性
 *
 *  JDK1.5之后推出包装类，解决基本类型不具备面向对象特性
 *
 *  抽象类（超类：父类）Number:
 *  所有包装类的父类：超类，本身抽象类，具备包装类的共有属性，没有给具体实现！
 *
 *  包位置：java.lang.Number
 *  特点：java语言中被定为编程的基本包，不需要调用，基本的类都在java.lang
 *
 *  实现类（子类）：BigDecimal、BigInteger、Byte、Double、Float
 *               Long、 Integer、Short  (子包装类)
 *  Object超类：子类 Boolean、Character
 *
 *  面向对象使用范围：封装---JavaBean ，定义私有属性:基本类型建议使用包装类进行替代
 *  private Integer i;
 *
 */
public class 包装类 {
    /**
     *  Number抽象类：超类
     *  抽象方法
     *  byteValue()   返回byte类型的值
     *  doubleValue() 返回double类型的值
     *  floatValue()   返回float类型的值
     *  intValue()    返回int类型的值
     *  longValue()   返回long类型的值
     *  shortValue() 返回short类型的值
     */
    @Test
    public void testNumber(){
        //实例化抽象类：Number---多态性
        Number n=new BigDecimal(-129);
        System.out.println(n.byteValue());  // -127
        //   byteValue()返回是一个byte类型----取值范围：-128~127  java补码运算
        // 正数超出---负数计算   负数超出---正数计算
        //返回的类型，可以根据值大小定接收的类型
        /*Number抽象类特点：直接赋值*/
        Number i=1;
        Number j=128;
        /*输出：i和j对象的所属类型*/
        System.out.println(i.getClass().getName());
        //Java.long.Integer
    }
    /**
     * 腾讯笔试题
     * BigDecimal--子类:实现类
     * 包位置:java.math.BigDecimal
     * 大数操作:针对小数，精确的计算(商业项母)
     * 1.000000000000000000000000001234565132
     * 用来对超过16位有效位的数进行精确计算
     * BigDecimal的性能比double和float差 在处理庞大的数据 复杂(小数位超长)运算效率明显
     * 缺点:平时用BigDecimal很少，除非商业项目，要求精准极高
     * 构造器有4种---不能有空对象 new BigDecimal() 报错
     * new BigDecimal(int)      创建一个具有参数所指定为整数的对象
     * new BigDecimal(double)   创建一个具有参数所指定双精度值的对象(不建议使用)
     * new BigDecimal(long)     创建一个具有参数所指定的长整数
     * new BigDecimal(String)   创建一个具有参数所指定的以字符串表示的数值
     */
    @Test
    public void testVal(){
        System.out.println(.2+.1);
        System.out.println(.3-.1);
        //计算机识别二进制 浮点数没有办法用二进制进行精确表示
        //cpu表示浮点数:指数、尾数、这样的表示方法损失一定的精度
        //BigDecimal的构造器，创建商业小数
        BigDecimal d1=new BigDecimal(.2);
        BigDecimal d2=new BigDecimal(.1);
        //d1和d2可以运算吗？     不可以运算
        //System.out.println(d1+d2);
        //BigDecimal对象--构造器。方法--(精度更准确)
    }
    /**如果，小数位准确不高，计算时采用BigDecimal对象如下方法
     * add(BigDecimal对象) BigDecimal对象种的值相加，返回BigDecimal对象
     * subtract(BigDecimal对象)BigDecimal对象种的值相减，返回BigDecimal对象
     * multiply(BigDecimal对象)BigDecimal对象种的值相乘，返回BigDecimal对象
     * divide(BigDecimal对象)BigDecimal对象种的值相除，返回BigDecimal对象
     *
     */
    @Test
    public void testVals(){
        BigDecimal d1=new BigDecimal(.2);
        BigDecimal d2=new BigDecimal(.1);
        //.2+.1=不损失精度的值
        d1.add(d2);
        System.out.println(d1.add(d2));
        //如上减法，乘法。除法、
        BigDecimal d3=new BigDecimal(.2);
        BigDecimal d4=new BigDecimal(.1);
        d3.subtract(d4);
        System.out.println(d3.subtract(d4));
        d1.multiply(d2);
        System.out.println(d1.multiply(d2));
        d1.divide(d2);
        System.out.println(d1.divide(d2));
        //ArithmeticException
    }
    /**
     * 以下都是重写Number(超类/父类)的方法
     * ToString()将BigDecimal对象的值转换为字符串
     * DoubleValue()将BigDecimal对象的值转换为双精度值
     * floatValue()将BigDecimal对象的值转换为单精度值
     * longValue()将BigDecimal对象的值转换为长整数值
     * intValue()将BigDecimal对象的值转换为整数值
     */
    @Test
    public void testXXXValue(){
        BigDecimal b1=new BigDecimal(.2);
       String s=  b1.toString(); //将BigDecimal对象的值转换为字符串
        // 请至少使用两种验证 b1转换为字符串
        System.out.println(s.getClass());   //利用Object对象
        System.out.println(1+s+1); //利用字符串拼接
        //多态  instanceof关键字:s是否是String对象的实例
        System.out.println(s instanceof String); //true 肯定是String
        //输出结果是int long  float double 类型
        //b1输出为整数型,舍去小数位
        System.out.println(b1.intValue());
        // b1输出为单精度值 小数不变
        System.out.println(b1.intValue());
        //b1输出为双精度:小数不变
        System.out.println(b1.doubleValue());
        //b1输出为长整数，舍去小数位,与整数输出一致
        System.out.println(b1.longValue());
    }
    /**巩固BigDecimal的使用
     * 已知:double d1=.2; double d2=.1;
     *     使用BigDecimal进行加法运算，得到的结果是十进制
     */
    @Test
    public void test(){
        //双精度定义d1和d2
        double d1=.2,d2=.1;
        //创建BigDecimal 相加 而且得到结果是0.3
        BigDecimal b1=new BigDecimal(Double.toString(d1));  //参数为字符串
        BigDecimal b2=new BigDecimal(Double.toString(d2));
        double result= b1.add(b2).doubleValue();
        System.out.println(result);
    }
    /**
     * BigDecimal 对象
     * compareTo():对BigDecimal对象比较大小
     * BigDecimal对象大小，由构造器传入值确定
     * 返回值: -1 第一个BigDecimal对象小于第二个BigDecimal对象
     *         0 第一个BigDecimal对象等于第二个BigDecimal对象
     *         1 第一个BigDecimal对象大于第二个BigDecimal对象
     */
    @Test
    public void testCompareTo(){
        BigDecimal d1=new BigDecimal(16);
        BigDecimal d2=new BigDecimal(15);
        System.out.println(d1.compareTo(d2)); //1
    }
    /**大数操作:针对整数---商业数值
     * BigInteger:子类(Number抽象类的实现类)
     * 什么情况下
     * 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
     * 构造方法6个 BigInteger(String str)将字符串作为BigInteger的数值，进行传入(常用)
     */
    @Test
    public void testBigI(){
        //创建对象 BigInteger
        BigInteger b1=new BigInteger("123456789");
        BigInteger b2=new BigInteger("12345678954546");
        /**
         * 大整数相加 引用类型<地址值>+引用类型<地址值></>
         * add(BigInteger对象) 两个BigInteger对象相加
         * subtract(BigInteger对象) 两个BigInteger对象相减
         * multiply(BigInteger对象) 两个BigInteger对象相乘
         * divide(BigInteger对象) 两个BigInteger对象相除
         * max() 求BigInteger对象的最大值
         * min() 求BigInteger对象的最小值
         * abs() 求BigInteger对象的绝对值
         *
         */
        System.out.println(b2.abs());
        System.out.println(b1.max(b2));  //两个BigInteger的最大值
        System.out.println(b2.min(b1));
        //测试BigInteger的值运算
    }
    /**Number超类
     * Integer、Byte、Double、Float、Long、Short 包装类
     * 对象中包装了一个对应类型的数值，int byte double long short
     * Integer极高包装类--JavaBean 私有属性int类型换成Integer(ID属性的属性值方法)
     * 包位置：Java.long.Integer
     * Integer构造器
     * Integer(int value): 以int型变量作为参数创建Integer对象(次常用)
     * Integer(String value):以String型变量作为参数创建Integer对象(常用)
     */
    @Test
    public  void testI(){
     //创建int类型值放入到Integer对象
        Integer i=new Integer(123);
        //将字符串类型值放入Integer对象中，注意:字符串可以写任意
        Integer r=new Integer("123四");
        //请问i与r可以相加吗？  引用类型+引用类型=自动拆装箱
        System.out.println("运算结果"+i+r);
    }
    /**包装类基本属性
     * 常量型:MAX_VALUE ,MIN_VALUE +-----字面量 死值
     * 用法:用于表示对应类型的取值范围
     * byte取值范围:-128~127
     *
     */
    @Test
    public void testMM(){
        //静态常量:通过《包装》类名直接调用 必须存在返回值 int最大值多少
        int imax=Integer.MAX_VALUE;   //int最大值 2147483647
        System.out.println(imax);
        //Long类型取值范围
        long limax= Long.MAX_VALUE;
        System.out.println(limax);
    }
    /**
     * Integer包装类
     * valueOf()方法:基本类型转换为包装类，建议使用此种方法装箱
     * 为什么？
     * ----装箱
     */
    @Test
    public  void testValueOf(){
        int i=10;  String s="10";
        //构造器装箱:两种方式
        Integer ir=new Integer(s);
        //ValueOf装箱:基本类型放入包装类 功能方法
        Integer ir1=Integer.valueOf(i);   //建议:JDK1.5之前增加静态方法valueOf方法
        Integer ir2=Integer.valueOf(s);   //建议:JDK1.5之前增加静态方法valueOf方法
        //int类型放入Integer对象中：装箱(两种)
    }
    /**
     * 拆箱
     * 包装类:intValue():把包装类转换为基本数据类型。建议使用intValue()取值
     *
     */
    @Test
    public void testIntValue(){
        //装箱与拆箱均选用方法 ValueOf装箱--  (取值与存值)
     Integer i1=   Integer.valueOf("10");
      Integer i2= Integer.valueOf(10);

      //将包装类 Integer:取出基本数据类型
        int i3=i1.intValue();
        int i4=i2.intValue();
        //麻烦--JDK1.5之前包装类存取值，不遍历(JDK1.5之后 交给编译器处理)
        //byte会出现精度溢出:存在值超出范围，建议:不使用byte short
        Integer d=Integer.valueOf(128);  //int的在取值范围比byte大 装箱int:整数
        System.out.println(d.byteValue()); //拆箱byte 128 -128
        /**
         * JDK1.5之后推出新特性:自动拆装箱
         * 允许编译器再编译代码时 将基本类型与引用类型之间互相赋值与操作:
         * 赋值时补全ValueOf以及xxxValue方法--自动转换
         */

    }
    @Test
    public void testAuto(){
        /**
         * 自动装箱过程:把基本类型转入包装类中
         * JDK1.5编译器自动处理
         * int d=new Integer(1).intValue();
         */
    int d=new Integer(1);
        /**自动拆箱过程:把包装类转入基本类型中
         * JDK1.5编译自动处理:
         * Integer i=Integer.ValueOf（d）
         *
         */
        Integer i=d;
        //自动拆装箱效果
        Integer is=1;//具备引用类型，还具备基本类型
        Integer is1=1;//is+is1=2 引用类型+引用类型
        is.hashCode(); //引用类型 哈希值
    }
    //包装类:方法重点  parseXXX()--Mysql+JavaBean+JDBC :解析接收的数值：真数值
    /**
     * 6个包装类：实现类
     * Integer实现类
     * toString(对应类型)
     * 包装类静态方法，可以获得到对应类型的字符串
     *
     */
    @Test
    public  void testToString(){
        //将基本类型转换为字符串(3种)
        int i=10;
        String s1=Integer.toString(i);//包装类的静态方法，通过逻辑得到数据拼出：域名
        String s2=i+"";
        String s3=String.valueOf(i);
        //将字符串转换为基本类型(2种)
        String s="123";
        int p1= Integer.valueOf(s);

    }

}

